#include "wrapper_os.h"
#ifdef CONFIG_AIRKISS_SUPPORT
#include "lwip/sockets.h"
#include "wifi_management.h"
#include "wifi_netlink.h"
#include "wifi_netif.h"
#include "malloc.h"
#include "debug_print.h"
#include "airkiss.h"

#define CONFIG_LWIP_LAYER         1

#define CHANNEL_SWITCH_TIME       100
#define AIRKISS_COMPLETE_TIME     60000

extern void wifi_set_connection_result(char *ssid, char *pwd);
static void wifi_promiscuous_rx(unsigned char *buf, unsigned short len, signed char rssi);

const airkiss_config_t akconf ={
    (airkiss_memset_fn)&sys_memset,
    (airkiss_memcpy_fn)&sys_memcpy,
    (airkiss_memcmp_fn)&sys_memcmp,
    (airkiss_printf_fn)&co_printf
};

static airkiss_control_t ak_ctrl;

static os_timer_t set_channel_timer;
static os_timer_t airkiss_timer;

airkiss_context_t *akcontext = NULL;

//static uint8_t gbssid[ETH_ALEN];

//for airkiss send notification
int g_UDPBCServerFd = -1;
struct sockaddr_in g_stUDPBCAddr;


#define DEVICE_TYPE "gh_5b95f2f5820d"
#define DEVICE_ID "gh_5b95f2f5820d_efccb20f06908c5f"
#define AIRKISS_LAN_PORT 12476
#define AIRKISS_BIND_PORT 12476

/*
    airkiss active send:
    send udp packets to 255.255.255.255(12476)
    packet is generated by airkiss_lan_pack.

    called about every 5s

*/
int airkiss_send_active_lan_discovery_packets(int client_socket_fd, int send_times,uint8_t *device_mac)
{
#if CONFIG_LWIP_LAYER
    int ret = -1;
    struct sockaddr_in to_addr;
    uint8_t lan_buf[200];
    uint16_t lan_buf_len = sizeof(lan_buf);
#if 1
    if (send_times != 1) {
        airkiss_printf(AIRKISS_ERROR, "airkiss_send_active_lan_discovery_packets fail!\n");
        return -1;
    }

#else
    if (send_times >= 50) {
        airkiss_printf(AIRKISS_ERROR, "send more than 50 times multiples 100ms delay, will exceed 5s!\n");
        return -1;
    }
#endif

    ret = airkiss_lan_pack(AIRKISS_LAN_SSDP_NOTIFY_CMD, DEVICE_TYPE, device_mac, 0, 0, lan_buf, &lan_buf_len, &akconf);
    if (ret != AIRKISS_LAN_PAKE_READY) {
        airkiss_printf(AIRKISS_ERROR, "airkiss pack lan packet error!");
        return -1;
    }


    FD_ZERO(&to_addr);
    to_addr.sin_family = AF_INET;
    to_addr.sin_port = htons(AIRKISS_LAN_PORT);
    to_addr.sin_addr.s_addr =inet_addr("255.255.255.255");


    while (send_times-- > 0) {
        airkiss_printf(AIRKISS_INFO, "airkiss_send_active_lan_discovery_packets !\n");
        sendto(client_socket_fd, (unsigned char *)lan_buf, lan_buf_len, 0, (struct sockaddr *) &to_addr, sizeof(struct sockaddr));
        sys_ms_sleep(100);
    }

#else
    airkiss_printf(AIRKISS_ERROR, "airkiss_send_active_lan_discovery_packets fail!!\n");
#endif

    return 0;
}

void airkiss_lan_server_reply(int client_socket_fd, struct sockaddr_in addr, char *pdata, unsigned short len,uint8_t* device_mac)
{
    int ret = -1;
    int pack_ret;
    uint8_t lan_buf[200];
    uint16_t lan_buf_len = sizeof(lan_buf);

    ret = airkiss_lan_recv(pdata, len, &akconf);

    switch (ret) {
    case AIRKISS_LAN_SSDP_REQ:
        airkiss_printf(AIRKISS_INFO, "Airkiss: packet is SSDP REQ!\n");
        addr.sin_port = htons(AIRKISS_LAN_PORT);
        lan_buf_len = sizeof(lan_buf);
        pack_ret = airkiss_lan_pack(AIRKISS_LAN_SSDP_RESP_CMD,  DEVICE_TYPE, DEVICE_ID, 0, 0, lan_buf, &lan_buf_len, &akconf);
        if (pack_ret != AIRKISS_LAN_PAKE_READY) {
            airkiss_printf(AIRKISS_ERROR, "airkiss_lan_pack error!\n");
            return;
        }

        airkiss_printf(AIRKISS_INFO, "airkiss_lan_server_reply !\n");
        sendto(client_socket_fd, (unsigned char *)lan_buf, lan_buf_len, 0, (struct sockaddr *) &addr, sizeof(struct sockaddr));
        break;
    default:
        airkiss_printf(AIRKISS_WARNING, "Airkiss: packet unknown!\n");
        break;
    }
}


int airkiss_lan_server_create(int client_socket_fd,uint8_t *device_mac)
{
    int server_sock_fd,len;
    struct sockaddr_in addr;
    int sock_timeout_val = 1000;
    int timeout_times = 0;
    int addr_len = sizeof(struct sockaddr_in);
    char buffer[256] = {0};


    printf("%s\n", __FUNCTION__);

    if((server_sock_fd = socket(AF_INET,SOCK_DGRAM,0)) < 0){
        airkiss_printf(AIRKISS_ERROR, "create sock error!");
        return -1;
    }

    memset(&addr, 0, sizeof(addr));
    addr.sin_family=AF_INET;
    addr.sin_port=htons(AIRKISS_BIND_PORT);
    addr.sin_addr.s_addr=htonl(INADDR_ANY) ;

    if (bind(server_sock_fd, (struct sockaddr *)&addr, sizeof(addr))<0) {
        airkiss_printf(AIRKISS_ERROR, "bind sock error!");
        return -1;
    }

    setsockopt(server_sock_fd, SOL_SOCKET, SO_RCVTIMEO, &sock_timeout_val, sizeof(sock_timeout_val));

    while(1) {
          memset(&buffer, 0, sizeof(buffer));
        len = recvfrom(server_sock_fd, buffer, sizeof(buffer), 0 , (struct sockaddr *)&addr, (socklen_t *)&addr_len);

        if (-1 == len) {
            /* timeout happens */
            timeout_times++;
            if (5 == timeout_times) {
                timeout_times = 0;
                //airkiss_send_active_lan_discovery_packets(server_sock_fd, 1, device_mac);
            }
        } else {
            /* packet received, filter and send back */
            airkiss_printf(AIRKISS_INFO, "receive size=%d, from %s\n", len, inet_ntoa( addr.sin_addr));
            airkiss_lan_server_reply(server_sock_fd, addr, buffer, len, device_mac);
        }
    }

}

/* this is a task */
void airkiss_lan_discovery_start(unsigned char *dev_mac)
{
    int airkiss_sock_active = -1;

#if 0/*use one socket*/
    airkiss_sock_active = socket(PF_INET, SOCK_DGRAM, IP_PROTO_UDP);
    if (airkiss_sock_active == -1) {
        airkiss_printf(AIRKISS_ERROR, "airkiss socket create fail\n");
        vTaskDelete(NULL);
    }
#endif
    airkiss_printf(AIRKISS_INFO, "airkiss_lan_discovery_start\n");
    airkiss_lan_server_create(airkiss_sock_active,dev_mac);
    //vTaskDelete(NULL);
}

int airkiss_createudpbroadcast(int udp_port)
{

    int ret = 0;
    int udpbufsize = 2;
    struct sockaddr_in g_stUDPBCServerAddr;

    if (g_UDPBCServerFd == -1) {

        g_UDPBCServerFd = socket(AF_INET, SOCK_DGRAM, 0);

        if (g_UDPBCServerFd < 0) {
            printf("UDP BC socket create error,g_UDPBCServerFd = %d\r\n",g_UDPBCServerFd);
            g_UDPBCServerFd = -1;
            ret = -1;
            return ret;
        }

        g_stUDPBCAddr.sin_family = AF_INET;
        g_stUDPBCAddr.sin_port = htons(udp_port);
        g_stUDPBCAddr.sin_addr.s_addr = htonl(0xffffffff);

        g_stUDPBCServerAddr.sin_family = AF_INET;
        g_stUDPBCServerAddr.sin_port = htons(udp_port);
        g_stUDPBCServerAddr.sin_addr.s_addr = htonl(INADDR_ANY);

        if (setsockopt(g_UDPBCServerFd, SOL_SOCKET, SO_BROADCAST, &udpbufsize,sizeof(int))!= 0) {
            ret = -1;
            printf("UDP BC Server setsockopt error\n");
            return ret;
        }
        if (bind(g_UDPBCServerFd, (struct sockaddr *)&g_stUDPBCServerAddr, sizeof(g_stUDPBCServerAddr))!= 0) {
            printf("UDP BC Server bind error\n");
            close(g_UDPBCServerFd);
            g_UDPBCServerFd = -1;
            ret = -1;
            return ret;
        }

    }
    printf("UDP BC Server socketid:%d on port:%d\n", g_UDPBCServerFd,udp_port);
    return ret;
}

void airkiss_send_notification(uint8_t random)
{
    int i = 0;
    if(airkiss_createudpbroadcast(10000) == -1){
        printf("create udp socket fail!\r\n");
        return;
    }

    for (i = 0; i <= 200; i++) {
        if (g_UDPBCServerFd > -1) {
            sendto(g_UDPBCServerFd, (char*)&random, 1, 0 ,(struct sockaddr*)&g_stUDPBCAddr, sizeof(g_stUDPBCAddr));
            sys_ms_sleep(2);
        }
    }
    close(g_UDPBCServerFd);
    g_UDPBCServerFd = 0;
    return;
}


void airkiss_deinit_content(void)
{
    //free airkiss context at last
    if(akcontext){
        sys_mfree(akcontext);
        akcontext = NULL;
    }

    sys_timer_delete(&set_channel_timer);
    sys_timer_delete(&airkiss_timer);
}


void airkiss_finish_task(void *parm)
{
    airkiss_context_t *context = (airkiss_context_t *)parm;
    int ret = 0;
    int retry = 2;
    int i;
    airkiss_result_t result;
    uint8_t *mac = NULL;

    ret = airkiss_get_result(context, &result);
    if (ret == 0) {
        airkiss_printf(AIRKISS_INFO,"\r\n airkiss get result ok,ssid = %s, pwd = %s,ssid length = %d,pwd length = %d,random = 0x%02x\r\n",
                   result.ssid, result.pwd, result.ssid_length,result.pwd_length,result.random);
    }
    else{
        airkiss_printf(AIRKISS_ERROR,"\r\n Airkiss get result failed!");
        goto task_del;
    }

    while (retry) {
        ret = wifi_management_connect((uint8_t *)result.ssid, (uint8_t *)result.pwd, TRUE);
        if(ret != 0){
            airkiss_printf(AIRKISS_ERROR, "\n\r Airkiss: wifi connect failed");
            airkiss_deinit_content();
            goto task_del;
        }

        for (i=0; i<30; i++) {
            sys_ms_sleep(1000);
            if (wifi_netlink_link_state_get() == WIFI_NETLINK_STATUS_LINKED_CONFIGED) {
                break;
            }
        }
        if (wifi_netlink_link_state_get() == WIFI_NETLINK_STATUS_LINKED_CONFIGED) {
            break;
        }
        retry--;
    }

    airkiss_deinit_content();

    //airkiss send notification
    airkiss_send_notification(result.random);

    //wifi_set_connection_result(result.ssid, result.pwd);

    mac = wifi_netif_get_hwaddr();
    airkiss_printf(AIRKISS_INFO, "airkiss dev mac = %02x %02x %02x %02x %02x %02x\r\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
    airkiss_lan_discovery_start(mac);

task_del:
    sys_task_delete(NULL);
}

void set_channel_timer_handler(void *p_tmr, void *p_arg)
{
    if(ak_ctrl.cur_channel >= 13)
        ak_ctrl.cur_channel = 1;
    else
        ak_ctrl.cur_channel ++;

    wifi_netlink_channel_set(ak_ctrl.cur_channel, CHANNEL_WIDTH_20, 0);
    /* inform airkiss we have changed channel */
    airkiss_change_channel(akcontext);

    sys_timer_start(&set_channel_timer, 0);
}

void airkiss_timeout_handler(void *p_tmr, void *p_arg)
{
    //int ret;

    airkiss_printf(AIRKISS_ERROR, "\r\n========= Airkiss: config timeout ! =========\r\n");

#if 0
    //init airkiss
    ret = airkiss_init(akcontext, &akconf);
    if(ret < 0){
        airkiss_printf(AIRKISS_ERROR,"Airkiss init failed!\r\n");
        return;
    }

    ak_ctrl.cur_channel = ak_ctrl.lock_channel;
    wifi_netlink_channel_set(ak_ctrl.cur_channel, CHANNEL_WIDTH_20, 0);

    sys_timer_start(&set_channel_timer, 0);
    sys_timer_start(&airkiss_timer, 0);
#else
    wifi_netlink_promisc_mode_set(0, NULL);
    airkiss_deinit_content();
#endif
}

static unsigned char promisc_rx_filter(unsigned char *buf, unsigned short len)
{
    unsigned char from_ap = 0;
    unsigned char from_sta = 0;
    unsigned short wlan_seq;
    unsigned char bcast_addr[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
#if DUPLICATED_OCTET_PATCH
    unsigned char i;
#endif

    if ((buf[1] & 0x03) == 2) {
        from_ap = 1;
    } else if ((buf[1] & 0x03) == 1) {
        from_sta = 1;
    }

    if (!from_ap && !from_sta) {
        return 0;
    }

    if (!ak_ctrl.channel_locked) {
        if (len <= 60 || len > 86) {
            return 0;
        }
        if (from_ap && (sys_memcmp(buf+4, bcast_addr, 6) != 0)) {
            return 0;
        }
        if (from_sta && (sys_memcmp(buf+4+6+6, bcast_addr, 6) != 0)) {
            return 0;
        }
    } else {

        if (len <= (ak_ctrl.lock_length - 6) || len > (512 + ak_ctrl.lock_length + 6)) {
            return 0;
        }
        wlan_seq = ((*(unsigned short *)(buf + 22)) & 0xfff0) >> 4;
        if (from_ap) {
            if ((sys_memcmp(buf+4, bcast_addr, 6) != 0)) {
                return 0;
            }
#if DUPLICATED_OCTET_PATCH
            if ((sys_memcmp(buf+4+6, ak_ctrl.wlan_hdr.addr1, 6) == 0) &&
                (sys_memcmp(buf+4+6+6, ak_ctrl.wlan_hdr.addr2, 6) == 0)) {
                if (len >= (256 + ak_ctrl.lock_length - 6) && len == ak_ctrl.last_ap_len && wlan_seq > ak_ctrl.last_ap_seq) {
                    for (i=0; i<4; i++) {
                        if (len == ak_ctrl.dup_len[i]) {
                            break;
                        } else if (ak_ctrl.dup_len[i] == 0) {
                            ak_ctrl.dup_len[i] = len;
                            airkiss_printf(AIRKISS_INFO,"========= wifi_promiscuous_rx, duplicated length %d =========\n", len + 4);
                            break;
                        }
                    }
                }
                ak_ctrl.last_ap_seq = wlan_seq;
                ak_ctrl.last_ap_len = len;
            }
#endif
        }
        if (from_sta) {
            if ((sys_memcmp(buf+4+6+6, bcast_addr, 6) != 0) ||
                (ak_ctrl.sta_seq_inited && (wlan_seq == ak_ctrl.last_sta_seq || ((wlan_seq - ak_ctrl.last_sta_seq) & 0x0fff) >= 0x0800))) {
                return 0;
            }
            if (sys_memcmp(buf+4+6, ak_ctrl.wlan_hdr.addr2, 6) == 0) {
                ak_ctrl.last_sta_seq = wlan_seq;
                if (!ak_ctrl.sta_seq_inited) {
                    ak_ctrl.sta_seq_inited = 1;
                }
            }
        }
    }

#if 0
    if (from_ap && (sys_memcmp(buf+4+6, ak_ctrl.wlan_hdr.addr1, 6) == 0) &&
        (sys_memcmp(buf+4+6+6, ak_ctrl.wlan_hdr.addr2, 6) == 0)) {
        airkiss_printf(AIRKISS_INFO,"wifi_promiscuous_rx, From AP, length is %d seq is %d\n", len + 4, wlan_seq);
    } else if (from_sta && (sys_memcmp(buf+4, ak_ctrl.wlan_hdr.addr1, 6) == 0) &&
        (sys_memcmp(buf+4+6, ak_ctrl.wlan_hdr.addr2, 6) == 0)) {
        airkiss_printf(AIRKISS_INFO,"wifi_promiscuous_rx, From STA, length is %d seq is %d\n", len + 4, wlan_seq);
    }
#endif

    return 1;
}

static unsigned char *length_rx_handle(unsigned short len, signed char rssi)
{
    unsigned char *tmp_buf;
    static unsigned short rssi_sum = 0;
    static unsigned char rssi_cnt = 0;
    unsigned char rssi_threshold;
#if DUPLICATED_OCTET_PATCH
    unsigned char i;
    unsigned char dup_possible = 0;
    static unsigned char toggle = 0;
#endif

    if (!ak_ctrl.channel_locked) {
        return NULL;
    } else {
        if (len <= (ak_ctrl.lock_length - 4) || len > (512 + ak_ctrl.lock_length + 6)) {
            return NULL;
        }
        if (len == ak_ctrl.last_rx_len) {
#if DUPLICATED_OCTET_PATCH
            for (i=0; i<4; i++) {
                if (len == ak_ctrl.dup_len[i] + 2) {
                    dup_possible = 1;
                    break;
                }
            }
            if (dup_possible) {
                toggle = !toggle;
                if (toggle) {
                    ak_ctrl.dup_len[i] = 0;
                } else {
                    return NULL;
                }
            } else {
                return NULL;
            }
#else
            return NULL;
#endif
        }
        if (!ak_ctrl.rssi_threshold_set && (len > ak_ctrl.lock_length - 4) && (len <= ak_ctrl.lock_length + 2)) {
            rssi_cnt++;
            rssi_sum += rssi;
            if (rssi_cnt == 16) {
                rssi_threshold = (rssi_sum >> 4) - 8;
                airkiss_printf(AIRKISS_INFO, "========= wifi_promiscuous_rx, set rssi threshold %d =========\n", rssi_threshold);
                wifi_netlink_promisc_filter_set(1, &rssi_threshold);
                ak_ctrl.rssi_threshold_set = 1;
                rssi_sum = 0;
                rssi_cnt = 0;
            }
        }
        ak_ctrl.last_rx_len = len;
        ak_ctrl.wlan_seq_num++;
        if (ak_ctrl.wlan_seq_num == 0x1000) {
            ak_ctrl.wlan_seq_num = 0;
        }
        ak_ctrl.wlan_hdr.seq_num = (ak_ctrl.wlan_seq_num << 4) & 0xfff0;
        ak_ctrl.wlan_hdr.duration = 48;
        tmp_buf = (unsigned char *)&ak_ctrl.wlan_hdr;
        tmp_buf[0] = 0x88;
        tmp_buf[1] = 0x41;
        //airkiss_printf(AIRKISS_INFO, "wifi_promiscuous_rx, length info %d rssi is %d seq is %d\n", len + 4, rssi, ak_ctrl.wlan_seq_num);
    }

    return tmp_buf;
}

static void wifi_lock_channel(unsigned char *buf, unsigned short len)
{
    unsigned char *bssid;

    if (!ak_ctrl.channel_locked) {
        if ((buf[1] & 0x03) == 1) {
            sys_memcpy(ak_ctrl.wlan_hdr.addr1, (buf + 4), 6);
            sys_memcpy(ak_ctrl.wlan_hdr.addr2, (buf + 4 + 6), 6);
            ak_ctrl.last_sta_seq = ((*(unsigned short *)(buf + 22)) & 0xfff0) >> 4;
            ak_ctrl.sta_seq_inited = 1;
        } else {
            sys_memcpy(ak_ctrl.wlan_hdr.addr1, (buf + 4 + 6), 6);
            sys_memcpy(ak_ctrl.wlan_hdr.addr2, (buf + 4 + 6 + 6), 6);
        }
        ak_ctrl.wlan_seq_num = ((*(unsigned short *)(buf + 22)) & 0xfff0) >> 4;
        bssid = ak_ctrl.wlan_hdr.addr1;
        ak_ctrl.lock_channel = wifi_netlink_ap_channel_get(bssid);
        if (ak_ctrl.lock_channel != 0) {
            wifi_netlink_channel_set(ak_ctrl.lock_channel, CHANNEL_WIDTH_20, 0);
        }
        ak_ctrl.lock_length = len;
        airkiss_printf(AIRKISS_INFO, "wifi_promiscuous_rx, lock length is %d\n", ak_ctrl.lock_length);
        wifi_netlink_promisc_filter_set(2, ak_ctrl.wlan_hdr.addr2);
        ak_ctrl.channel_locked = 1;
    }
}

static void wifi_promiscuous_rx(unsigned char *buf, unsigned short len, signed char rssi)
{
    int ret;
    void *handle;
    unsigned char *tmp_buf = buf;

    if (buf != NULL) {
        if (promisc_rx_filter(buf, len) == 0) {
            return;
        }
    } else {
        tmp_buf = length_rx_handle(len, rssi);
        if (tmp_buf == NULL) {
            return;
        }
    }

    ret = airkiss_recv(akcontext, tmp_buf, len);

    if (ret == AIRKISS_STATUS_CHANNEL_LOCKED) {
        airkiss_printf(AIRKISS_INFO,"========= Airkiss: channel locked! =========\r\n");
        sys_timer_stop(&set_channel_timer, 0);
        wifi_lock_channel(buf, len);
    } else if (ret == AIRKISS_STATUS_COMPLETE) {
        sys_timer_stop(&airkiss_timer, 0);
        wifi_netlink_promisc_mode_set(0, NULL);
        airkiss_printf(AIRKISS_INFO,"========= Airkiss: quit promiscuous mode! =========\r\n");

        handle = sys_task_create(NULL, (const uint8_t *)"airkiss_finish", NULL,
                    AIRKISS_FINISH_STACK_SIZE, 0, AIRKISS_FINISH_TASK_PRIO,
                    (task_func_t)airkiss_finish_task, akcontext);
        if (handle == NULL) {
            airkiss_printf(AIRKISS_ERROR, "\nAirkiss: create airkiss finish task failed.\n");
        }
    }
}


int airkiss_init_content(airkiss_context_t **content)
{
    int ret = 0;
    int i;

    //free airkiss context if still exists
    if(*content){
        sys_mfree(*content);
        *content = NULL;
    }

    //init airkiss context
    *content = (airkiss_context_t *)sys_malloc(sizeof(airkiss_context_t));
    if(!(*content)){
        airkiss_printf(AIRKISS_ERROR,"\n\rAlloc airkiss context failed!");
        ret = -1;
        return ret;
    }

    //init airkiss
    ret = airkiss_init(*content,&akconf);
    if (ret < 0) {
        airkiss_printf(AIRKISS_ERROR,"Airkiss init failed!\r\n");
        return ret;
    } else {
        airkiss_printf(AIRKISS_INFO, "------Airkiss init ok!\r\n");
    }

    ak_ctrl.channel_locked = 0;
    ak_ctrl.cur_channel = 1;
    ak_ctrl.lock_channel = 1;
    ak_ctrl.lock_length = 0;
    ak_ctrl.wlan_seq_num = 0;
    ak_ctrl.sta_seq_inited = 0;
    ak_ctrl.rssi_threshold_set = 0;
    ak_ctrl.last_rx_len = 0;
    sys_memset((unsigned char *)&ak_ctrl.wlan_hdr, 0, sizeof(wlan_header_t));
    for (i=0; i<6; i++) {
        ak_ctrl.wlan_hdr.addr3[i] = 0xff;
    }

#if DUPLICATED_OCTET_PATCH
    ak_ctrl.last_ap_len = 0;
    for (i=0; i<4; i++) {
        ak_ctrl.dup_len[i] = 0;
    }
#endif

    return 0;
}

int airkiss_start(void)
{
    char ret = 0;
    unsigned short len_threshold;
#if AIRKISS_ENABLE_CRYPT
    const char *key = "wechatiothardwav";
#endif

    //get airkiss version
    airkiss_printf(AIRKISS_INFO,"\n\rAirkiss version %s",airkiss_version());
    if (airkiss_init_content(&akcontext) < 0) {
        airkiss_printf(AIRKISS_ERROR,"Airkiss init fail!\n");
        return -1;
    }

#if AIRKISS_ENABLE_CRYPT
    airkiss_set_key(akcontext, (const unsigned char *)key, strlen(key));
#endif

    /* get all 802.11 packets*/
    wifi_netlink_promisc_mode_set(1, wifi_promiscuous_rx);
    len_threshold = 0x280;
    wifi_netlink_promisc_filter_set(0, (unsigned char *)&len_threshold);

    sys_timer_init(&set_channel_timer, "set_ch_timer", CHANNEL_SWITCH_TIME, 0,
                (timer_func_t)set_channel_timer_handler, NULL);

    sys_timer_init(&airkiss_timer, "airkiss_timer", AIRKISS_COMPLETE_TIME, 0,
                (timer_func_t)airkiss_timeout_handler, NULL);

    wifi_netlink_channel_set(ak_ctrl.cur_channel, CHANNEL_WIDTH_20, 0);

    sys_timer_start(&set_channel_timer, 0);
    sys_timer_start(&airkiss_timer, 0);

    return ret;
}

#endif
